package cn.cc.goods.service.serviceImpl;

import cn.cc.common.beanCopy.utils.BeanCopierUtil;
import cn.cc.common.contants.RedisKeyConstant;
import cn.cc.common.encrypt.EncryptUtil;
import cn.cc.common.redis.RedisCommon;
import cn.cc.common.result.utils.RestResult;
import cn.cc.common.result.utils.RestResultEmum;
import cn.cc.common.utils.MapToBeans;
import cn.cc.goods.controller.vo.EsResultSourceVO;
import cn.cc.goods.init.InitGoods;
import cn.cc.goods.service.GoodsService;
import cn.cc.goods.service.GoodsSkuService;
import cn.cc.goods.service.GoodsSpuService;
import cn.cc.goods.service.GoodsTypeService;
import cn.cc.goods.service.bo.*;
import cn.cc.goods.service.domain.*;
import cn.hutool.core.lang.generator.ObjectIdGenerator;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: smail-mi-cloud
 * @description: 商品主体功能实现
 * @author: Mr.WuChao
 * @create: 2021-07-17 09:23
 **/
@Service
public class GoodsServiceImpl extends InitGoods implements GoodsService {
    @Autowired
    private RedisCommon redisCommon;
    @Autowired
    private GoodsTypeService typeService;
    @Autowired
    private GoodsSpuService spuService;
    @Autowired
    private GoodsSkuService skuService;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public RestResult<GetGoodsSkuAndSpuDO> getGoodsSkuAndSpu(String spuId) {
        //先去redis查找数据
        //取sku数据
        List<GetGoodsSkuDO> skuLists = redisCommon.getList(RedisKeyConstant.SHOPPING_CAR_GOODS_CC_GOODS_SKU, GetGoodsSkuDO.class);
        //取spu数据
        Map spuMap = redisCommon.getHashAll(RedisKeyConstant.SHOPPING_CAR_GOODS_CC_GOODS_SPU, GetGoodsSpuDO.class);
        //取出类型
        Map typeMap = redisCommon.getHashAll(RedisKeyConstant.SHOPPING_CAR_GOODS_CC_GOODS_TYPE, GetGoodsTypeDO.class);
        //判断sku数据
        if (null == skuLists || skuLists.size() == 0) {
            List<GetGoodsSkuDO> data = skuService.getGoodSkuAll().getData();
            if (null == data || data.size() == 0) {
                return new RestResult(RestResultEmum.EXIT_ERROR.code, RestResultEmum.EXIT_ERROR.msg);
            }
            List<GetGoodsSkuDO> skuDOS = BeanCopierUtil.copyList(data, GetGoodsSkuDO.class);
            for (GetGoodsSkuDO skuDO : skuDOS) {
                //将数据拷贝到skulist
                skuLists.add(skuDO);
            }
        }
        List<GetGoodsSkuDO> list = new ArrayList<>();
        //循环redis所查到的数据
        for (GetGoodsSkuDO skuDO : skuLists) {
            //取出符合条件的集合
            if (spuId.equals(skuDO.getGoodsId())) {
                list.add(skuDO);
            }
        }
        //随机取出符合条件的一组数据
        int i = (int) (Math.random() * list.size());
        //sku数据
        GetGoodsSkuDO goodsSkuDO = list.get(i);
        //判断spu数据
        if (null == spuMap || spuMap.size() == 0) {
            List<GetGoodsSpuDO> data = spuService.getGoodsSpu().getData();
            if (data.size() == 0 || null == data) {
                return new RestResult(RestResultEmum.EXIT_ERROR.code, RestResultEmum.EXIT_ERROR.msg);
            }
            for (GetGoodsSpuDO datum : data) {
                //将数据放到map
                spuMap.put(datum.getGoodsId(), datum);
            }
        }
        Object spu = spuMap.get(spuId);
        if (null == spu) {
            return new RestResult(RestResultEmum.EXIT_ERROR.code, RestResultEmum.EXIT_ERROR.msg);
        }
        //把spu数据拷贝到新的类
        GetGoodsSkuAndSpuDO andSpuDO = BeanCopierUtil.copyObj(spu, GetGoodsSkuAndSpuDO.class);
        //判断type数据
        if (null == typeMap || typeMap.size() == 0) {
            List<GetGoodsTypeDO> data = typeService.getGoodsTypeAll().getData();
            if (data.size() == 0 || null == data) {
                return new RestResult(RestResultEmum.EXIT_ERROR.code, RestResultEmum.EXIT_ERROR.msg);
            }
            for (GetGoodsTypeDO datum : data) {
                //将数据放到map
                typeMap.put(datum.getGoodsType(), datum);
            }
        }
        //判断spu数据是否能和类型表对应
        if (null == typeMap.get(andSpuDO.getGoodsType())) {
            return new RestResult(RestResultEmum.EXIT_ERROR.code, RestResultEmum.EXIT_ERROR.msg);
        }
        //添加商品规格
        andSpuDO.setGoodsStandard(goodsSkuDO.getGoodsStandard());
        //添加商品库存
        andSpuDO.setGoodsRepertory(goodsSkuDO.getGoodsRepertory());
        //商品状态(有货无货)
        andSpuDO.setGoodsStatusStop(goodsSkuDO.getGoodsStatus());
        //商品价格
        andSpuDO.setGoodsPrice(goodsSkuDO.getGoodsPrice());
        //skuid
        andSpuDO.setSkuId(goodsSkuDO.getSkuId());
        return new RestResult(andSpuDO);
    }

    @Override
    public RestResult<Map<String, EsResultSourceDO>> esGetSpuName(String index, String spuName) throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //高亮构建器
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<span style='color:blue'>");//高亮前缀
        highlightBuilder.postTags("</span>");//高亮后缀
        highlightBuilder.field("goods_name");//高亮字段
        //条件查询所有数据
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("goods_name", spuName);
        sourceBuilder.query(matchQueryBuilder);
        sourceBuilder.highlighter(highlightBuilder);//放进高亮
        searchRequest.source(sourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest);
        //将数据存入map
        Map<String, EsResultSourceDO> maps = new HashMap<>();
        for (SearchHit hit : search.getHits()) {
            //查询数据
            Map<String, Object> map = hit.getSourceAsMap();
            //高亮数据
            Map<String, HighlightField> fields = hit.getHighlightFields();
            //迭代器
            Iterator<HighlightField> iterator = fields.values().iterator();
            String str = iterator.next().toString();
            //将map数据转为javaBean
            EsResultSourceDO sourceDO = MapToBeans.getObject(map, EsResultSourceDO.class);
            maps.put(str, sourceDO);
        }
        return new RestResult<>(maps);
    }

    @Override
    public RestResult<Void> addGoods(AddGoodsSkuAndSpuBO goods)  {
        goods.setCreationDate(new Date());
        goods.setVersion("1");
        goods.setCreatedBy("cc");
        goods.setModifyDate(new Date());
        //自动生成id
        long l = System.currentTimeMillis();//时间戳
        String mi = String.valueOf(l);
        EncryptUtil instance = EncryptUtil.getInstance();
        String rs = instance.MD5(mi);
        goods.setSkuId(rs);
        ObjectIdGenerator objectIdGenerator = new ObjectIdGenerator();
        String id = objectIdGenerator.next();
        goods.setGoodsId(id);
        AddGoodsSkuBO skuBO = BeanCopierUtil.copyObj(goods, AddGoodsSkuBO.class);
        AddGoodsSpuBO spuBO = BeanCopierUtil.copyObj(goods, AddGoodsSpuBO.class);
        RestResult<Void> result = skuService.addGoodSkuOne(skuBO);
        RestResult<Void> result1 = spuService.addGoodSpuOne(spuBO);
        if (result.getCode().equals(RestResultEmum.SUCCESS.code) && result1.getCode().equals(RestResultEmum.SUCCESS.code)) {
            return new RestResult<>(RestResultEmum.SUCCESS.code, RestResultEmum.SUCCESS.code);
        }
        return new RestResult<>(RestResultEmum.SAVE_ERROR.code, RestResultEmum.SAVE_ERROR.code);
    }

    @Override
    public RestResult<Void> updGoods(UpdGoodsSkuAndSpuBO goods) {
        UpdGoodsSkuBO skuBO = BeanCopierUtil.copyObj(goods, UpdGoodsSkuBO.class);
        UpdGoodsSpuBO spuBO = BeanCopierUtil.copyObj(goods, UpdGoodsSpuBO.class);
        RestResult<Void> result = skuService.updGoodsSku(skuBO);
        RestResult<Void> result1 = spuService.updGoodsSpu(spuBO);
        if (result.getCode().equals(RestResultEmum.SUCCESS.code) && result1.getCode().equals(RestResultEmum.SUCCESS.code)) {
            return new RestResult<>(RestResultEmum.SUCCESS.code, RestResultEmum.SUCCESS.code);
        }
        return new RestResult<>(RestResultEmum.EDIT_ERROR.code, RestResultEmum.EDIT_ERROR.code);
    }

    @Override
    public RestResult<Void> delGoods(DelGoodsSkuAndSpuBO goods) {
        DelGoodsSkuBO skuBO = BeanCopierUtil.copyObj(goods, DelGoodsSkuBO.class);
        DelGoodsSpuBO spuBO = BeanCopierUtil.copyObj(goods, DelGoodsSpuBO.class);
        RestResult<Void> result = skuService.delGoodsSku(skuBO);
        RestResult<Void> result1 = spuService.delGoodsSpu(spuBO);
        if (result.getCode().equals(RestResultEmum.SUCCESS.code) && result1.getCode().equals(RestResultEmum.SUCCESS.code)) {
            return new RestResult<>(RestResultEmum.SUCCESS.code, RestResultEmum.SUCCESS.code);
        }
        return new RestResult<>(RestResultEmum.DEL_ERROR.code, RestResultEmum.DEL_ERROR.code);

    }
}
